As developed in [WP 1.2.C], a VHDL entity-architecture pair can be viewed as class. The entity corresponds to the class interface, providing a set of subprogram (method) declarations and data fields (attributes). In a corresponding architecture, the methods can be implemented and called from concurrent statements. Thus, instances (objects) can provide concurrency and activity by themselves. This class concept is in tune with the present VHDL standard.
Adding an inheritance feature to entities and architectures is what has to be done according to the Language Architecture Document. Comparing the entity-architecture class notion to class type concepts known from software--one class implementation per class interface--it would be logical to derive new entity-architecture pairs (i.e. design entities) from old ones since classes are derived as a whole. But an entity can have several architectures, and it would be inconsistent to bind a derived entity to a single derived architecture. Rather, several derived architectures should be permitted to coexist, representing implementations at different levels of abstraction or with different styles of description.
A derived entity declaration extends the interface provided by another entity (derived or non-derived). It may also specify additional declarations and statements that are part of the derived design entity. A given derived entity declaration may be shared by many design entities, each of which has a different architecture.
derived_entity_declaration ::= entity identifier is new entity_name with derived_entity_header derived_entity_declarative_part [ begin derived_entity_statement_part ] end [ entity ] [ entity_simple_name ] ;
Inheritance relationship: The entity denoted by the identifier is called direct descendant of or derived from the entity denoted by entity_name. Vice versa, entity_name is called direct ancestor of or extended by entity 'identifier'. An entity E' is descendant of an entity E if E' is a direct descendant or if its ancestor is a descendant of E. An entity E is an ancestor of an entity E' if E is a direct ancestor or if one of its descendants is an ancestor of E'. An indirect descendant (ancestor, resp.) is a descendant (ancestor, resp.) which is not a direct descendant (ancestor, resp.)
Non-cyclic inheritance: A derived entity must not be an ancestor of its ancestor.
The derived entity header and declarative part as well as the optional concurrent statement part are present in each design entity whose interface is defined by the derived entity declaration.
If a simple name appears at the end of a derived entity declaration, it must repeat the identifier of the derived entity declaration.
Example: Interface of a register of D-flipflops extended for inverted output.
entity DREG is generic( Width : Positive ); port( D : in Bit_vector( 0 to Width - 1 ); Q : buffer Bit_vector( 0 to Width - 1 ); Clk : in Bit ); end entity DREG; entity DREGN is new DREG with port( QN : out Bit_vector( 0 to Width - 1 ) ); end entity DREGN; entity EREGN is new DREGN with port( Enable : in Bit ); end entity EREGN;
Anchor: A derived entity is a new kind of primary unit, similar to simple entities. A name of a derived entity may appear wherever the name of a non-derived entity can appear.
primary_unit ::= entity_declaration | derived_entity_declaration -- new | configuration_declaration | package_declaration
A derived entity header shares the syntax of an entity header, having the potential to declare ports and generics for communication with the environment. In addition to the semantic rules concerning entity headers, special inheritance rules apply to derived entity headers with respect to the headers of the derived entity's ancestors.
derived_entity_header ::= [ formal_generic_clause ] [ formal_port_clause ]
Effective port and generic lists as defined below define the full interface of a derived entity. They take the function of a regular entity's port and generic lists wherever a derived entity is used instead of an entity.
Effective port list: The effective port list of a non-derived entity is the port list defined in its entity header. The set of port names declared in a derived entity header must be disjoint from the effective port list of its ancestor. The effective port list of the derived entity is then formed by appending to its direct ancestor's effective port list the port list declared in its derived entity header.
Effective generic list: An analogous definition holds for the effective generic list. The effective generic list of a non-derived entity is its generic list. A derived entity's effective generic list is the concatenation of its direct ancestor's effective generic list and its own generic list if both are disjoint. Else an error is generated.
Note: The recursive definition of effective interface lists implies that it is the union of all ports declared in the headers of all its ancestors. Moreover, the ordering of interface objects is defined through concatenation ordering according to the inheritance relationship. The analogue holds for generics.
Rationale: Effective interface lists are needed to instantiate derived design entities, see 3.6. Therefore, extending the scope of ports and generics to derived entities is not sufficient to define inheritance of interfaces.
The derived entity declarative part has the same syntactic shape as an entity declarative part. It allows to declare items that are common to all design entities that have the derived entity as their interface. Semantics differ with respect to the inheritance of declarations from ancestor entities and the possibility to redefine subprogram bodies which are regarded as method implementations.
derived_entity_declarative_part ::=
{ entity_declarative_item }
Names declared by declarative items in the declarative part of an entity or its ancestors are visible within the bodies of corresponding design entities, as well as within certain portions of a corresponding configuration declaration.
Inheritance of declarations: The term inheritance is used as synonym of implicit declaration in the context of declarative parts of derived entities. Inheritance is defined by means of the following rules:
Note: Signals and shared variables declared in the entity are regarded as attributes in the object-oriented sense. Procedures and functions declared in this place are regarded as methods. The corresponding subprogram bodies should be declared in the corresponding architecture(s) to hide the implementation from the user.
Example: A Memory as the basis for ROM and RAM.
use Work.MessagePackage.all; entity Memory is generic( Size : Positive := 2**16 ); port( Message : in MemoryMsg'CLASS; Reply : out MemoryRpl'CLASS ); subtype AddressRange is Natural range 0 to Size - 1; use Work.DataTypePackage.MemDatum; type MemDataType is array ( AddressRange ) of MemDatum'CLASS; shared variable Data : MemDataType; procedure Read( constant Address : in AddressRange; variable Datum : out MemDatum'CLASS ); procedure Init; end Memory; entity ROM is new Memory with generic( FileName : String ); end ROM; use Work.DataTypePackage.MemDatum; use Work.DataTypePackage.Uninitialized; entity RAM is new Memory with generic( InitialValue : MemDatum'CLASS := Uninitialized ); procedure Write( constant Address : in AddressRange; constant Datum : in MemDatum'CLASS ); end RAM;
Syntax of a derived entity statement part corresponds to an entity statement part. Its assertions and passive concurrent statements forms together with assertions and passive concurrent statements inherited from ancestors the effective entity statement part that is common to each design entity with this interface.
derived_entity_statement_part ::=
{ entity_statement }
Effective entity statement part: An effective entity statement part takes the place of a regular entity's statement part wherever a derived entity is used instead of an entity: The effective entity statement part of a non-derived entity is its entity statement part. The effective entity statement part of a derived entity is the union of
Note: The above rules define the inheritance and redefinition of (labelled) concurrent statements. The ordering of concurrent statements in the effective entity statement part is undefined and left to the implementor.
The VHDL architecture body is extended for an optional additional keyword abstract after the keyword is.
architecture_body ::= architecture identifier of entity_name is [ abstract ] architecture_declarative_part begin architecture_statement_part end [ architecture ] [ architecture_simple_name ] ;
Abstractness: An architecture declared with the keyword abstract is said to be an abstract architecture. An abstract architecture together with its corresponding entity may contain subprogram declarations without a corresponding subprogram body. The name of an abstract architecture must not appear in any instantiation or configuration.
Note: An abstract architecture cannot become part of a design hierachy to be simulated. But derived architectures can be non-abstract if they add the missing subprogram bodies.
In addition to the inheritance of interfaces provided by entities, the declaration of derived architecture bodies allows to inherit, extend, and modify the relationships between the inputs and outputs specified by another architecture.
derived_architecture_body ::= architecture identifier of entity_name_#1 is new [ abstract ] architecture_name [ of entity_name_#2 ] with derived_architecture_declarative_part begin derived_architecture_statement_part end [ architecture ] [ architecture_simple_name ] ;
The identifier defines the simple name of the architecture. Only this name may--but does not have to--appear at the end of the declaration. The architecture that is inherited from is specified in the new ... with clause.
Abstractness: A derived architecture declared with the keyword abstract is said to be an abstract (derived) architecture. In the declarative region of an abstract derived architecture and its corresponding entity there may be explicit or implicit (inherited) subprogram declarations without a corresponding subprogram body. The name of an abstract derived architecture must not appear in any instantiation or configuration.
Note: Abstractness is not inherited.
Compatibility with entity inheritance: Either of the following cases must be fulfilled to ensure compatibility of architecture inheritance with the inheritance relationship between entities:
It is an error if none of the above cases is true. Furthermore it is an error if architecture_name does not denote an architecture of entity_name_#2.
Rationale: Architecture code may use declarations from the architecture's entity. When inheriting from an architecture, these declarations must also be inherited.
Example: Architectures of register entities (cf. 3.2)
architecture Behavior of DREG is begin P : process( Clk ) begin if Clk = '1' then Q <= D; end if; end process; end architecture Behavior; architecture Behavior of DREGN is new Behavior of DREG with begin QN <= not Q; end Behavior; architecture Behavior of EREGN is new Behavior of DREGN with begin P : process( Clk ) begin if Clk = '1' and Enable = '1' then Q <= D; end if; end process; end architecture Behavior;
Anchor: A derived architecture is a secondary unit, similar to simple architectures. Moreover, a derived_architecture_name may appear everywhere an architecture_name can appear.
secondary_unit ::= architecture_body | derived_architecture_body -- new | package_body
The derived architecture declarative part has the same syntax as an architecture declarative part. Semantics differ with respect to inheritance of declarations from ancestor design units and the possibility to redefine subprogram bodies which are regarded as method implementations.
derived_architecture_declarative_part ::=
{ block_declarative_item }
Inheritance of declarations: The term inheritance is used as synonym of implicit declaration in the context of declarative parts of derived architectures. Inheritance is defined by means of the following rules:
Syntax of a derived architecture statement part corresponds to an architecture statement part. Its concurrent statements form together with those inherited from ancestors the effective architecture statement part.
derived_architecture_statement_part ::=
{ concurrent_statement }
Effective architecture statement part: The effective architecture statement part of a non-derived architecture is its architecture statement part. The effective architecture statement part of a derived architecture is the union of
Note: The above rules define the inheritance and redefinition of (labelled) concurrent statements. The ordering of concurrent statements in the effective statement part is undefined and left to the implementor. Concurrent statement of the architecture's entity or its ancestors cannot be redefined by an architecture.
Example: Architectures of memory entities.
architecture ObjectOriented of Memory is abstract procedure Read( constant Address : in AddressRange; variable Datum : out MemDatum'CLASS ) is begin Datum := Data( Address ); end; begin DISPATCHER : process( Message'TRANSACTION ) begin Message.dispatch( Reply ); end process; end ObjectOriented; architecture ObjectOriented of ROM is new ObjectOriented of Memory with type MemDatumFile is file of MemDatum'CLASS; procedure Init is file F : MemDatumFile; begin FILE_OPEN( F, FileName, READ_MODE ); for Address in AddressRange loop exit when ENDFILE( F ); READ( F, Data( Address ) ); end loop; FILE_CLOSE( F ); end; begin end ObjectOriented; architecture ObjectOriented of RAM is new ObjectOriented of Memory with procedure Init is begin Data := ( others => InitialValue ); end; procedure Write( constant Address : in AddressRange; constant Datum : in MemDatum'CLASS ) is begin Data( Address ) := Datum; end; begin end ObjectOriented;
The VHDL rule that every declaration of a subprogram must be accompanied immediately by a corresponding subprogram body within the same declarative region is weakened in the case of the declarative region formed by an entity and a corresponding abstract architecture. If an abstract architecture does not define a subprogram body although the subprogram is declared (in either the corresponding entity or the architecture itself), no error is generated. In other words, the definition of a subprogram body may be deferred to derived design units.
Note: An abstract architecture cannot be used to form and instantiate a design entity (see 3.6.1).
Declarative region: A derived entity, together with a corresponding architecture (which is not necessarily a derived architecture), forms a single declarative region.
Visibility: A declaration hidden through inheritance can be made visible by selection using the name of the ancestor unit (entity or architecture, resp.) it was originally declared in explicitly.
Note: Declarations are inherited primarily to preserve the functionality of inherited code. Inherited declarations are not intended to be used extensively in added code. But in some cases it may be useful to gain access to hidden data fields or hidden method implementations, e.g. to reuse the inherited functionality in a hiding method implementation.
Prefix THIS: The name THIS is implicitly declared in each entity, derived entity, architecture, and derived architecture. When a subprogram call prefixed with THIS is inherited by any derived unit, and a redeclared version of the called subprogram exists in the derived unit, this redeclared subprogram will be executed in the derived unit instead of the subprogram originally called in the parent unit.
Use clauses: Names of (ancestor) units must not be used in use clauses to achieve direct visibility of hidden declarations.
An entity aspect of the form entity_name [(architecture_name)] may include a derived entity or a derived architecture (or both). The architecture must be associated in its declaration with the entity name, and it must not be abstract. In absence of an architecture name, default binding rules apply. It is an error if an abstract architecture is selected for default binding.
Example: Instantiation of registers (cf. 3.2).
entity ShiftRegister is generic( NoOfBits : Positive ); port( Shift_in : in Bit; Shift_out : out Bit; Direction : in Bit; Shift_enable: in Bit; Clk : in Bit ); end ShiftRegister; architecture Structure of ShiftRegister is component EREGN generic( Width : Positive ); port( D : in Bit_vector( 0 to NoOfBits - 1 ); Q : out Bit_vector( 0 to NoOfBits - 1 ); Clk : in Bit; QN : out Bit_vector( 0 to NoOfBits - 1 ); Enable : in Bit ); end component; signal State, NextState : Bit_vector( 0 to NoOfBits - 1 ); begin I1 : EREGN generic map ( Width => NoOfBits ) port map ( D => NextState, Q => State, QN => open, Clk => Clk, Enable => Shift_enable ); NextState <= State( 1 to NoOfBits - 1 ) & Shift_in when Direction = '0' else Shift_in & State( 0 to NoOfBits - 2 ); Shift_out <= State( 0 ) when Direction = '0' else State( NoOfBits - 1 ); end Structure; -- The component EREGN is bound to the entity Work.EREGN by default rules -- because their names are identical and the component's interface lists are -- identical to the effective interface lists of the derived entity EREGN. -- If for instance the positions of Q and Clk were exchanged in the component's -- port list, a configuration declaration or specification would be required, e.g.: configuration CONF of ShiftRegister is for Structure for all : EREGN use entity WORK.EREGN( Behavior ) generic map( Width ) -- positional association port map( D => D, Q => Q, QN => QN, -- named association Clk => Clk, Enable => Enable ); end for; end for; end CONF;
An instantiated unit specified by the clause "entity entity_name [(architecture_name)]" may include a derived entity or a derived architecture (or both). If specified, the architecture must correspond to the entity and must not be abstract. If no architecture is specified, default binding rules apply, and an error is generated if they select an abstract entity.
Example: Instantiation of memories (cf. 3.2.2).
entity Testbench is end Testbench; -- The following architecture body is illegal because default binding selects -- the abstract architecture ObjectOriented of entity Memory. architecture A of Testbench is signal Message : Work.MessagePackage.MemoryMsg'CLASS; begin CACHE : entity Memory port map( Message => Message ); end A; -- The following is legal. Default binding applies to PROG_MEM, whereas -- for DATA_MEM the architecture ObjectOriented is explicitly specified. architecture B of Testbench is signal Msg_P, Msg_D : Work.MessagePackage.MemoryMsg'CLASS; begin DATA_MEM : entity RAM( ObjectOriented ) port map( Msg_D ); PROG_MEM : entity ROM generic map( "test" ) port map( Msg_P ); end B;
Every block or component instantiated in the effective architecture statement part can be configured as defined in LRM section 1.3.1. In particular, inherited blocks or components must be configured also in case they have been configured for an ancestor.
A derived entity must be analysed after its ancestor entity. A derived architecture must be analysed after its ancestor architecture and after the (derived) entity it corresponds to.
Derived design entities, i.e. entity-architecture pairs formed with derived entity or derived architecture, are elaborated like regular design entities, with the following modifications: